﻿#include "LogMaster.h"
#include <ossThread.h>
#include <ossTime.h>
#include <json/ossJson.h>
#include <ossDir.h>
#include <OssList.h>
#include <ossString.h>


BEGIN_OSS_MESSAGE_MAP(LogMaster, LabelMasterDriver)
	OSS_COMMAND("getLogMsg",OnGetLogMsg)
END_OSS_MESSAGE_MAP()

LogMaster::LogMaster(LabelDeviceBase* pParent)
	:LabelMasterDriver(pParent)
	,m_hFileHandle(NULL)
	,m_iFileIndex(0)
	,m_iCurrSize(0)
{
}

LogMaster::~LogMaster(void)
{
	if (m_hFileHandle)
	{
		OssWriteFile(m_hFileHandle,"程序退出\n",sizeof("程序退出\n")-1);//写入文件
		OssCloseFile(m_hFileHandle);
		m_hFileHandle = NULL;
	}
}

BOOL LogMaster::DeviceInit(OssJson& initJson)
{
	//初始化日志文件
	InitLogMaster(initJson);

	RegisterListenData(LD_LOG, (DeviceReportFun)&LogMaster::OnDeviceLogInfoReport, this);

	return LabelMasterDriver::DeviceInit(initJson);
}

BOOL LogMaster::DeviceDeinit()
{
	RevokeListenData(LD_LOG, (DeviceReportFun)&LogMaster::OnDeviceLogInfoReport, this);

	return LabelMasterDriver::DeviceDeinit();
}

BOOL LogMaster::DeviceStart()
{
	return LabelMasterDriver::DeviceStart();
}

BOOL LogMaster::DeviceStop()
{
	return	LabelMasterDriver::DeviceStop();
}

void LogMaster::OnDeviceLogInfoReport(LdDataType tDataType, OssJson& jsonReportData)
{
	OssJson& deviceId = jsonReportData["deviceId"];
	OssJson& msg = jsonReportData["msg"];
	OssJson& priority = msg["priority"];
	OssJson& dateTime = msg["dateTime"];
	OssJson& logInfo = msg["logInfo"];

	OssAutoCritical autoCritical(m_fileCritical);
	if (m_hFileHandle == NULL || m_iCurrSize > m_iFileMaxSize)
	{
		if (m_hFileHandle)
		{
			OssCloseFile(m_hFileHandle);
			m_hFileHandle = NULL;
		}
		
		char acFileName[OSS_MAX_PATH];

		m_iFileIndex ++;
		if (m_iFileIndex >= m_iFileNumMax)
		{
			m_iFileIndex = 0;
		}
		OssSnprintf(acFileName,sizeof(acFileName),"%s/log-%d.log", m_acLogPath,m_iFileIndex);//
		m_hFileHandle = OssOpenFile(acFileName,"wb");
		m_iCurrSize = 0;
	}

	if (m_hFileHandle)
	{
		char acTitle[100];
		int iLen = OssSnprintf(acTitle, sizeof(acTitle), "%03d %s %s :", priority.asInt(), dateTime.asCString(), deviceId.asCString());
		OssWriteFile(m_hFileHandle, acTitle, iLen);
		OssWriteFile(m_hFileHandle, logInfo.asCString(), logInfo.Size()-1);//写入文件
		m_iCurrSize += logInfo.Size() + iLen;
	}
}

/**
	*		初始化日志管理
	*/
void LogMaster::InitLogMaster(OssJson& initJson)
{
	OssJson& logPath = initJson["logPath"];
	OssStrncpy(m_acLogPath, logPath.asCString(), sizeof(m_acLogPath));
	m_iFileNumMax = initJson["fileNumMax"].asInt();

	if (m_iFileNumMax <= 0)
	{
		m_iFileNumMax = 10;
	}

	m_iFileMaxSize = initJson["fileMaxSize"].asInt();
	if (m_iFileMaxSize < 10*1024)
	{
		m_iFileMaxSize = 10*1024;
	}

	if (!OssIsExistDirectory(logPath.asCString()))  //判断目录是否存在
	{
		OssCreateDirectory(logPath.asCString());
	}

	char acFileName[OSS_MAX_PATH];
	OssFindFileData ffd;

	OssSnprintf(acFileName,sizeof(acFileName),"%s/*.log", m_acLogPath);//
	HANDLE hFind = OssFindFirstFile(acFileName,&ffd);

	if (hFind == NULL)
	{
		OssSnprintf(acFileName,sizeof(acFileName),"%s/log-0.log", m_acLogPath);//
		m_hFileHandle = OssOpenFile(acFileName,"wb+");
		m_iCurrSize = 0;
		m_iFileIndex = 0;

		return ;
	}

	//找当前最大的序号
	int iMaxIndex = 0;
	do 
	{
		if (OssStrcmp(ffd.cFileName,".") == 0 || OssStrcmp(ffd.cFileName,"..") == 0 )
		{
			continue;
		}

		char* pcIndex = OssStrstr(ffd.cFileName,"-");

		//如果不符合要求则需要删除本文件
		if (pcIndex == NULL)
		{
			OssSnprintf(acFileName,sizeof(acFileName),"%s/%s", m_acLogPath,ffd.cFileName);//
			OssDeleteFile(acFileName);
			continue;
		}

		int iIndex = OssAtoi(pcIndex+1);
		if (iMaxIndex < iIndex)
		{
			iMaxIndex = iIndex;
		}
	} while (OssFindNextFile(hFind,&ffd));
	OssCloseFindFile(hFind);

	//重新遍历一遍，将序号小于（iMaxIndex-10）的删除
	OssSnprintf(acFileName,sizeof(acFileName),"%s/*.log", m_acLogPath);//
	hFind = OssFindFirstFile(acFileName,&ffd);
	if (hFind == NULL)
	{
		return ;
	}

	do 
	{
		if (OssStrcmp(ffd.cFileName,".") == 0 || OssStrcmp(ffd.cFileName,"..") == 0 )
		{
			continue;
		}

		char* pcIndex = OssStrstr(ffd.cFileName,"-");
		if (pcIndex)
		{
			int iIndex = OssAtoi(pcIndex+1);
			if (iIndex < iMaxIndex - 10)
			{
				OssSnprintf(acFileName,sizeof(acFileName),"%s/%s", m_acLogPath,ffd.cFileName);//
				OssDeleteFile(acFileName);
			}
		}

	} while (OssFindNextFile(hFind,&ffd));
	OssCloseFindFile(hFind);
	
	//打开最后一个文件
	OssSnprintf(acFileName,sizeof(acFileName),"%s/log-%d.log", m_acLogPath,iMaxIndex);//
	m_hFileHandle = OssOpenFile(acFileName,"ab+");
	if (m_hFileHandle)
	{
		m_iCurrSize = OssGetFileSize(m_hFileHandle);
		m_iFileIndex = iMaxIndex;
	}
}


/**
	 *		获取日志信息请求
	 */
int LogMaster::OnGetLogMsg(WPARAM wParam, LPARAM lParam)
{
	OssJson& request = *(OssJson*)wParam;

	//tsId是回馈数据的唯一ID，必须和接收者一致，否则会找错。
	//requestp["tsId"] = requestp["tsId"];
	request["msgId"] = "getLogMsgRsp";
	request["to"] = request["from"];
	request["from"] = GetDeviceId();
	request["result"] = "success";
	
	OssJson& msg = request["msg"];
	LONG64 size = msg["size"].asInt();
	if (size < 100)
	{
		size = 100;
	}

	do
	{
		char acFileName[OSS_MAX_PATH];

		OssSnprintf(acFileName, sizeof(acFileName), "%s/log-%d.log", m_acLogPath, m_iFileIndex);//
		
		OssAutoCritical autoCritical(m_fileCritical);
		if (m_hFileHandle != nullptr)
		{
			OssCloseFile(m_hFileHandle);
		}

		m_hFileHandle = OssOpenFile(acFileName, "rb");
		if (m_hFileHandle == nullptr)
		{
			request["result"] = "log file not open";
			break;
		}

		int iSize = size * 100;
		if (iSize > m_iCurrSize)
		{
			iSize = m_iCurrSize;
		}
		OssFileSeek(m_hFileHandle, -iSize, SEEK_END);
		char* pcData = new char[iSize + 10];
		if (pcData == nullptr)
		{
			request["result"] = "malloc failed";
			break;
		}

		int iRead = OssReadFile(m_hFileHandle, pcData, iSize);
		if (iRead <= 0)
		{
			request["result"] = "read file error";
			delete[]pcData;
			break;
		}

		OssJson& logInfos = msg["logInfos"];
		pcData[iRead] = 0;
		char* log = OssStrstr(pcData, "\n");
		OssJson logInfo;
		while (log)
		{
			log = OssSkipToD(log);
			char* logEnd = OssStrstr(log, "\n");
			if (logEnd == nullptr)
			{
				break;
			}

			*logEnd = '\0';
			logInfos.Push(log);

			log = logEnd + 1;
		}

		delete[]pcData;
		

		OssCloseFile(m_hFileHandle);
		m_hFileHandle = OssOpenFile(acFileName, "ab+");
	} while (false);
	
	SendResponse(request);
	return MSG_OK;
}





